Zurück in Elementare ProgrammentwicklungWeiter in Elementare ProgrammentwicklungSuche in Datenfeldern Zusammenfassung ?

Wer im Telefonbuch sucht, kann drei Suchstrategien einsetzen:

Die folgende Tabelle fasst die drei Suchstrategien zusammen und nennt ihre Vor- und Nachteile. Eine schnelle Suchstrategie stellt grössere Anforderungen an die Organisation der Daten und an das Vorwissen des Benutzers:

Suche Suchbeispiel Bedingung Effizienz
direkt Seite 143 Seiten nummeriert sehr schnell
sequentiell 061 / 422 13 07 keine langsam
binär Bohnenblust Fritz Einträge sortiert schnell

Ein konventionelles Telefonbuch ist ähnlich wie ein Datenfeld organisiert. Eine Seite entspricht einer Zelle, und eine Seitennummer entspricht dem Index. Wir bilden deshalb die drei Suchstrategien auf unser Datenfeld Läufer ab.

1 Direkte Suche

Direkt suchen heisst mit einem gegebenen Indexwert ein Feldelement bestimmen. Wenn zum Beispiel nach dem Namen des dritten Läufers gefragt wird, so lautet die Antwort:

Name = Läufer(3)

2 Sequentielle Suche

Sequentiell suchen heisst hintereinander jedes Element mit einem Suchwert vergleichen, bis die Suche Erfolg hat. Wenn zum Beispiel nach der Nummer der Läuferin Dora gefragt wird, so lautet die Antwort: Vergleiche der Reihe nach alle Elemente, bis die Nummer auftaucht:

For Nummer = 1 To 5
  If Läufer(Nummer) = “Dora” Then
    MsgBox “Nummer von Dora = ” & Nummer
    Exit For
  End If
Next Nummer

Die Zählschleife (For ... Next) geht solange von Zelle zu Zelle, bis der Inhalt des laufenden Elements mit “Dora” übereinstimmt. Dann wird in einem Ausgabefeld “Nummer von Dora =” und die gefundene Nummer ausgegeben (& verknüpft die Stringkonstante mit Nummer und konvertiert dabei die Zahl Nummer automatisch in einen String). Weil die Suche nun beendet ist, verlässt die Anweisung Exit For die Zählschleife. Wir erweitern deshalb die Syntax der Zählschleife:

Dim Index As Integer

For
Index = <Untergrenze> To <Obergrenze>
    <Anweisungen>
    [Exit For]
    <Anweisungen>]
Next Index

Exit For steht in eckigen Klammern, weil es weggelassen werden kann, falls die Schleife nicht mitten im Schleifenkörper verlassen werden muss.

Aufgabe Schreiben Sie die sequentielle Suche b) mit einer While-Schleife.

Aufgabe Übung Maximum

3 Binäre Suche

a) Spezifikation

Wer im Telefonbuch binär sucht, ...

Eine solche Suche heisst Binärsuche. Sie halbiert ein sortiertes Datenfeld solange, bis das gesuchte Element gefunden wird. Bevor wir die Binärsuche in VBA ausdrücken, beschreiben wir sie entwurfssprachlich. Wir verwenden dazu das Datenfeld Läufer und starten mit dem Beispielaufruf ...

sucheBinär(1,7, "Paul", 4)

Das erste Argument enthält die Untergrenze des zu durchsuchenden Feldbereichs. Beim ersten Aufruf von sucheBinär deckt der Feldbereich noch das ganze Datenfeld Läufer ab Spätere Aufrufe durchsuchen einen immer kleineren Teil. Beim ersten Aufruf ist deshalb die Obergrenze 7. Das dritte Argument entspricht dem Suchwert “Paul” und das vierte Argument nennt die Mitte des Feldbereichs. Vor dem ersten Aufruf ist die Mitte (1 + 7) / 2 = 4. Vor jedem weiteren Aufruf wird die Mitte neu berechnet.

Die folgende Tabelle erweitert unser Läuferbeispiel um die Zellen 6 und 7 und zeigt in den Schritten 1 bis 3 die binäre Suche nach “Paul”:

Nr

1

2

3

4

5

6

7

Läufer(Nr)

ANNA

BRUNO

DORA

FRANZ

KARIN

NORA

PAUL

Schritt (1)

L

M

R

Schritt (2)

L

M

R

Schritt (3)

L, M, R

Links        Indexwert der Untergrenze des jeweils betrachteten Feldbereichs
Mitte        Indexwert der Mitte des jeweils betrachteten Feldbereichs
Rechts      Indexwert der Obergrenze des jeweils betrachteten Feldbereichs

Gesucht sei die Startnummer von Paul. In der Tabelle erkennen Sie sofort das Suchergebnis 7. Weil der Computer nicht über die menschliche Fähigkeit des unmittelbaren Erkennens von Mustern verfügt, müssen wir ihm die Binärsuche schrittweise beibringen (Schritt in Klammern):

Zuerst ermittelt der Algorithmus aus den Positionsindizes Links und Rechts den Index Mitte (1). Weil der Läufer der Position Mitte (Franz) nicht gleich Paul ist, sucht der Algorithmus weiter. Paul ist alphabetisch grösser als Franz. Deshalb wird der rechte Teil des Datenfelds weiter untersucht: Die neue Mitte berechnet sich wieder aus Links und Rechts (2). Die Läuferin an der neuen Position von Mitte heisst Nora und ist ebenfalls kleiner als Paul. Weil jetzt der rechte Teil des Datenfelds nur noch aus einer einzigen Zelle besteht, fallen die Positionen Links, Rechts und Mitte zusammen und der Läufer an der Position Mitte entspricht dem Suchwert Paul (3).

b) Entwurf

Der verbalen Beschreibung entspricht der folgende entwurfssprachliche Algorithmus. Wir gehen wiederum von gleichen Aufruf aus:

sucheBinär(1,7, "Paul", 4)
sucheBinär(links,rechts, Name, Mitte)
  Mitte = (links + rechts) \ 2 					‘ganzzahlige Division
  Falls links <= Mitte dann
    Falls Name = Feld(Mitte) dann
      Name gefunden
    sonst
      Falls Name < Feld(Mitte) dann
        sucheBinär(links,Mitte-1, Name, Mitte)
      sonst Name > Feld(Mitte)
        sucheBinär(Mitte+1,rechts, Name, Mitte)
  sonst Name nicht gefunden

Der Rückwärtsstrich-Operator \ hinterlässt den ganzzahligen Anteil der Gleitkommadivision /. Zum Beispiel ergibt 5 \ 2 statt der Gleitkommazahl 2.5 die Ganzahl 2. Der Algorithmus ruft sich je nach Bedingung mit einer der fett gedruckten Anweisungen selbst wieder auf. Er heisst deshalb rekursiv (von lat. recurrere = zurücklaufen). Die folgende Geschichte veranschaulicht den Grundgedanken der Rekursion:

Ein Hund kam in die Küche und stahl dem Koch ein Ei,
da nahm der Koch den Löffel und schlug den Hund entzwei,
da kamen viele Hunde und gruben ihm ein Grab und setzten ihm einen Grabstein, worauf geschrieben stand:
        Ein Hund kam in die Küche und stahl dem Koch ein Ei,
        da nahm der Koch den Löffel und schlug den Hund entzwei,
        da kamen viele Hunde und gruben ihm ein Grab und setzten ihm einen Grabstein, worauf geschrieben stand:
                ...

Diese Geschichte ist rekursiv, weil sie sich selbst aufruft, indem sie auf die vorangehende Geschichte zurückspringt. Die Katze beisst sich also in den Schwanz. Im Gegensatz zu dieser Hundegeschichte ist aber sucheBinär endlich rekursiv. Ein endlich rekursives Programm ruft sich nur solange auf, bis eine Endbedingung erfüllt wird. In unserem Fall ist die Endbedingung dann erfüllt, wenn der Name auf der Position Mitte gleich dem gesuchten Namen ist.

c) Implementation

Wenn Sie auf die Startschaltfläche von sucheBinär.xls klicken, dann erscheint ein Eingabefeld, das Sie nach einem gross geschriebenen Suchnamen - zum Beispiel NORA - frägt (siehe Bild unten). Die gefundene Zellnummer wird dann in einem Ausgabefeld angezeigt, andernfalls erscheint die Fehlermeldung “Kein Element mit diesem Wert”. Ereignisprozedur der Schaltfläche »Suche binär ist die Subroutine sucheBinär() (siehe Code unten).

Damit das Datenfeld Läufer sowohl in der Subroutine sucheBinär() als auch in der aufgerufenden Funktion gefunden gelesen werden kann, vereinbaren wir es mit Private (statt Dim). So ist es im ganzen Modul, und nicht nur in einer bestimmten Prozedur, bekannt:

Private Läufer(1 To 7) As String

Besser wäre allerdings eine Vereinbarung von Läufer in der Subroutine sucheBinär() und eine Übergabe des Datenfelds Läufer als Argument an die Funktion gefunden:

If gefunden(Läufer, 1,7, Suchname, Nr) = True Then ...

Datenfelder wie Läufer können aber in einzelnen Programmiersprachen, insbesondere in älteren Versionen von Visual Basic, keine Argumente von Prozeduren sein. Wir belassen es deshalb bei der Private-Vereinbarung.

Die folgenden Abbildungen zeigen die Anwender- und Entwicklersicht der Binärsuche. gefunden(links,rechts, Läufername, Mitte) ist eine boolsche Funktion, welche die entwurfssprachliche Version der Binärsuche implementiert. Sie ergibt True, falls der Suchname im Datenfeld vorkommt, sonst False. Die Nummer der gefundenen Zelle wird als Argument Mitte zurückgegeben.

Anwendersicht
Anwendersicht der Arbeitsmappe sucheBinär.xls
Entwicklersicht

Aufgabe Übung sucheIterativBinär


Rekursion in einem Installationsskript (veranschaulicht die praktische Anwendung der Rekursion)